package engine;

/**
 * 
 * @author Dylan
 * 
 *         Basic vector class implementation. Should expand to include more
 *         advanced vector manipulation, possibly interface with matrix and
 *         point classes. This class is also used to represent points, as there
 *         would be lots of redundant code otherwise. Be careful to keep a
 *         distinction between points and vectors - they are not mathematically
 *         the same!
 * 
 */

public class Vector {
	private double x, y;

	public Vector() { // Initialize empty vector
	}

	public Vector(double x, double y) {
		this.x = x;
		this.y = y;
	}
	
	public Vector(String x, String y) {
		this.x = Integer.parseInt(x);
		this.y = Integer.parseInt(y);
	}

	/*
	 * Advanced vector operations
	 */

	public double length() {
		return (double) Math.sqrt(x * x + y * y);
	}

	public double lengthSquared() {
		return x * x + y * y;
	}

	public Vector normalize() { // Return unit vector with same direction
		if (x == 0 && y == 0){
			return new Vector();
		} else {
			return scale(1 / length());
		}
	}

	public double dotProduct(Vector vector) {
		return x * vector.x + y * vector.y;
	}
	
	public double crossProductZ(Vector vector) {
		return getX() * vector.getY() - getY() * vector.getX();
	}

	public Vector projection(Vector vector) { // Project onto another vector
		double length = vector.length();
		return vector.scale(dotProduct(vector) / (length * length));
	}

	public Vector perpendicular(Vector vector) { // Orthogonal to projection
		// Return parallel to another vector.
		// Only use if projection not calculated.
		// Otherwise use previously calculated projection and subtract().
		return subtract(projection(vector));
	}
	
	/*
	 * Convert the vector into a polar vector
	 */
	public PolarVector toPolarVector(){
		return new PolarVector(Math.atan2(y, x), length());
	}
	

	/*
	 * Point operations
	 */

	public double distance(Vector point) {
		return subtract(point).length();
	}

	public double distanceSquared(Vector point) {
		return subtract(point).lengthSquared();
	}

	/*
	 * Basic operations
	 */

	public Vector add(Vector vector) {
		return new Vector(this.x + vector.x, this.y + vector.y);
	}

	public Vector subtract(Vector vector) {
		return add(vector.scale(-1));
	}

	public Vector scale(double scalar) {
		return new Vector(this.x * scalar, this.y * scalar);
	}

	/*
	 * Setting and getting values
	 */

	public double getX() {
		return x;
	}

	public double getY() {
		return y;
	}

	public void setX(double x) {
		this.x = x;
	}

	public void setY(double y) {
		this.y = y;
	}
	
	public void print() {
		System.out.println("["+x+", "+y+"]");
	}
}
